package platform;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jgroups.Address;

import communication.Communicator;
import communication.GroupResponse;
import communication.ParameterizedMessage;
import communication.ParameterizedMessageImpl;
import communication.Response;

public class MasterServer {
	
	private Communicator serviceBus;
	
	public MasterServer() {
		serviceBus = new Communicator("SERVICE_BUS");
	}
	
	public void startService(String serviceName) {
		ParameterizedMessage msg = buildStartServiceMessage(serviceName);
		
		GroupResponse res = serviceBus.castMessage(msg);
		
		logResponses(res);

	}

	private ParameterizedMessage buildStartServiceMessage(String serviceName) {
		int index = serviceName.lastIndexOf('.');
		
		String pureName = serviceName.substring(++index);
		
		Logger logger = Logger.getLogger(MasterServer.class);
		
		logger.info("Send command to start the service name: " + pureName + " type: " + serviceName);
		
		ParameterizedMessage msg = new ParameterizedMessageImpl("ServiceControl:StartService");
		
		msg.setParameter("name", serviceName);
		
		msg.setParameter("fileName", pureName + ".jar");
		return msg;
	}
	
	public void startService(String serviceName, String slaveName) {
		ParameterizedMessage msg = buildStartServiceMessage(serviceName);
		
		Logger logger = Logger.getLogger(MasterServer.class);
		
		boolean matched = false;
		
		for(Address slave : serviceBus.getAllMembers()) {
			if (slave.toString().equals(slaveName)) {
				matched = true;
				
				logger.info("Deploy target is : " + slaveName);
				
				ParameterizedMessage responseMsg = serviceBus.sendMessage(slave, msg);
				
				logger.info("The result is : " + responseMsg.getParameter("result"));
			}
		}
		
		if (!matched) {
			logger.error(slaveName + " is not a valid slave ID.");
		}

	}
	
	public void stopService(String serviceName) {
		ParameterizedMessage msg = new ParameterizedMessageImpl("ServiceControl:StopService");
		msg.setParameter("target", serviceName);
		
		GroupResponse res = serviceBus.castMessage(msg);
		
		logResponses(res);
	}

	private void logResponses(GroupResponse res) {
		Logger logger = Logger.getLogger(MasterServer.class);
		for(Response response : res.getResponses()) {
			logger.info(response.getSender().toString() + " : "
					+ response.getMessage().getParameter("result"));
		}
	}
	
	public void serviceStatus() {
		ParameterizedMessage msg = new ParameterizedMessageImpl("ServiceControl:Status");
		
		GroupResponse res = serviceBus.castMessage(msg);
		
		Logger logger = Logger.getLogger(MasterServer.class);
		int runningServiceCount = 0;
		for(Response response : res.getResponses()) {
			String serviceStatus = response.getMessage().getParameter("status");
			if (serviceStatus == null) {
				continue;
			}
			
			++runningServiceCount;
			
			String serviceName = response.getMessage().getParameter("name");
			
			logger.info(response.getSender().toString() + " : "
					+ serviceName + " is " + serviceStatus);
		}
		
		if (0 == runningServiceCount) {
			logger.info("No service is running.");
		}

	}
	
	public static void main(String[] args) throws Exception {
		BasicConfigurator.configure();
		Logger.getLogger("org.jgroups").setLevel(Level.ERROR);
		
		MasterServer server = new MasterServer();
		
		String command;
		
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

		
		while ((command = in.readLine()) != null) {
			String[] cmds = command.split(" ");
			String cmd = cmds[0].toLowerCase();
			if (cmd.equals("start")) {
				if (cmds.length <= 2) {
					server.startService(cmds[1]);
				} else {
					server.startService(cmds[1], cmds[2]);
				}
			}
			else if (cmd.equals("stop")) {
				server.stopService(cmds[1]);
			}
			else if (cmd.equals("exit")) {
				server.serviceBus.close();
				break;
			}
			else if (cmd.equals("status")) {
				server.serviceStatus();
			}
			
		}
	
		
	}

}
